package com.kancy.okhttp.client.service.impl;

import com.alibaba.fastjson.JSON;
import com.kancy.okhttp.client.service.HttpClient;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * OkHttpClientImpl
 *
 * @author kancy
 * @date 2020/5/1 15:16
 */
public class OkHttpClientImpl implements HttpClient {
    private final RestTemplate restTemplate;

    public OkHttpClientImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 发送GET请求
     *
     * @param url
     * @param responseClass 返回类型
     * @return
     */
    @Override
    public <T> T sendGet(String url, Class<T> responseClass, Object ... params) {
        return restTemplate.getForObject(String.format(url, params), responseClass);
    }

    /**
     * 发送GET请求
     *
     * @param url 地址
     * @param header 请求头
     * @param responseClass 返回类型
     * @return
     */
    @Override
    public <T> T sendGet(String url, Object header, Class<T> responseClass, Object ... params) {
        HttpEntity request = new HttpEntity(getHttpHeaders(header));
        // 构造execute()执行所需要的参数。
        RequestCallback requestCallback = restTemplate.httpEntityCallback(request, responseClass);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = restTemplate.responseEntityExtractor(responseClass);
        ResponseEntity<T> response = restTemplate.execute(String.format(url, params), HttpMethod.GET, requestCallback, responseExtractor);
        return response.getBody();
    }

    /**
     * 发送GET请求
     *
     * @param url 请求地址：http://ip:port/url/%s/%s?param1=%d&param2=%s
     * @param params     参数
     * @return
     */
    @Override
    public String sendGet(String url, Object... params) {
        return restTemplate.getForObject( String.format(url, params), String.class);
    }

    /**
     * 发送POST请求
     *
     * @param url
     * @return
     */
    @Override
    public String sendPost(String url, Object ... params) {
        return restTemplate.postForObject(String.format(url, params), null, String.class);
    }

    /**
     * 发送POST请求
     *
     * @param url      地址
     * @param jsonBody 请求体
     * @return
     */
    @Override
    public String sendPost(String url, Object jsonBody, Object ... params) {
        return restTemplate.postForObject(String.format(url, params), jsonBody, String.class);
    }

    /**
     * 发送POST请求
     *
     * @param url      地址
     * @param jsonBody 请求体
     * @param responseClass 返回类型
     * @return
     */
    @Override
    public <T> T sendPost(String url, Object jsonBody, Class<T> responseClass, Object ... params) {
        return restTemplate.postForObject(String.format(url, params), jsonBody, responseClass);
    }

    /**
     * 发送POST请求
     *
     * @param url      地址
     * @param jsonBody 请求体
     * @param header   请求头 , 实体或者Map
     * @param responseClass   返回类型
     * @return
     */
    @Override
    public <T> T sendPost(String url, Object jsonBody, Object header, Class<T> responseClass, Object ... params) {
        HttpEntity request = new HttpEntity(jsonBody, getHttpHeaders(header));
        // 构造execute()执行所需要的参数。
        RequestCallback requestCallback = restTemplate.httpEntityCallback(request, responseClass);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = restTemplate.responseEntityExtractor(responseClass);
        ResponseEntity<T> response = restTemplate.execute(String.format(url, params), HttpMethod.POST, requestCallback, responseExtractor);
        return response.getBody();
    }

    /**
     * 转换请求头
     * @param header
     * @return
     */
    @NotNull
    private HttpHeaders getHttpHeaders(Object header) {
        HttpHeaders headers = new HttpHeaders();
        if (Objects.nonNull(header)){
            HashMap<String, Object> headerMap = JSON.parseObject(JSON.toJSONString(header), HashMap.class);
            for (Map.Entry<String, Object> entry : headerMap.entrySet()) {
                headers.add(entry.getKey(),
                        Objects.isNull(entry.getValue()) ? "" : String.valueOf(entry.getValue()));
            }
        }
        return headers;
    }
}
